iT邦幫忙

2021 iThome 鐵人賽

DAY 21
1
Modern Web

JavaScript Easy Go!系列 第 21

#21 讓 Automation 與 Chat Bot 連動

  • 分享至 

  • xImage
  •  

今天我們要讓之前的程式能跟 Chat Bot 連動。

需要 Worker 嗎?

直接從程式中 POST 過去啊,難道還要透過 Worker?

對沒錯,不用,我們可以直接從程式中處理。

回顧

讓我們回顧一下我們的 checker 函式:

async function checker(courses) {
    // 一樣,確認子頁面存在再操作
    await page.waitForSelector("#stfseldListDo");
    const child_page = await (await page.$("#stfseldListDo")).contentFrame();

    // 用無窮迴圈重複執行,直到想停止時手動結束程式
    while (true) {
        // 遍歷每個課程,檢查是否有可加選的課程
        for (let i = 0; i < courses.length; i++) {
            // 在子頁面中注入程式確認課程人數狀態,後方是帶入的查詢參數
            const data = await child_page.evaluate(injection.getInfo, courses[i].code, courses[i].class, courses[i].type, courses[i].form);
            courses[i].seats = data.限修人數 - data.已分發人數;
        }

        // 印出所有可加選課程
        console.log(
            "---\n" +
                courses
                    .filter((course) => course.seats > 0)
                    .map((course) => `${course.name} 還有 ${course.seats} 個空位`)
                    .join("\n")
        );

        // 冷卻時間,避免癱瘓系統
        await child_page.waitForTimeout(30 * 1000);
    }
}

我們這裡會一直印出有空位的課以及空多少位置。

但你總不希望一直被訊息騷擾吧?所以我們會在位置發生變動時再發送訊息。

程式

我們需要先加上 node-fetch Package:

npm i node-fetch@2

然後引入:

const fetch = require("node-fetch");

send 函式

就是傳訊息的函式:

async function send(msg) {
    // 發送訊息
    await fetch(`https://api.telegram.org/bot${process.env.TOKEN}/sendMessage`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ chat_id: +process.env.CHAT_ID, parse_mode: "MarkdownV2", text: msg }),
    });
}

這裡我們用環境變數來儲存 TOKEN 及 CHAT_ID。(當然你也可以一起放到 config 裡面)
至於 CHAT_ID 要怎麼取得?你就在 Bot 上寫個回傳 Chat_ID 的東西就好啦。

// Bot
if (text === "id") {
    await fetch(`https://api.telegram.org/bot${TOKEN}/sendMessage`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        // 回覆 Chat ID
        body: JSON.stringify({ chat_id, parse_mode: "MarkdownV2", text: chat_id.toString() }),
    });
}

新的 checker

async function checker(courses) {
    // 一樣,確認子頁面存在再操作
    await page.waitForSelector("#stfseldListDo");
    const child_page = await (await page.$("#stfseldListDo")).contentFrame();

    // 這裡多了個儲存空位狀態的東西
    const seats = {};

    // 用無窮迴圈重複執行,直到想停止時手動結束程式
    while (true) {
        // 遍歷每個課程,檢查是否有可加選的課程
        for (let i = 0; i < courses.length; i++) {
            // 在子頁面中注入程式確認課程人數狀態,後方是帶入的查詢參數
            const data = await child_page.evaluate(injection.getInfo, courses[i].code, courses[i].class, courses[i].type, courses[i].form);
            courses[i].seats = data.限修人數 - data.已分發人數;
        }

        // 空位數有變化再放進來
        const changed = {};
        courses
            .forEach((course) => {
                if (seats[course.name] !== course.seats) {
                    // 空位數有變化
                    changed[course.name] = course.seats;
                    seats[course.name] = course.seats; // 更新空位數
                }
            });

        // 如果有空位數有變化,傳送訊息
        if (Object.keys(changed).length > 0) {
            // 只發送有位置的訊息,可以發送 Markdown 格式的訊息
            let msg = Object.entries(changed)
                .map(([name, seats]) => (seats ? `${name} 目前有 **${seats}** 個空位` : ""))
                .filter((x) => !!x)
                .join("\n");
            // 沒有 await 的必要,因為不影響
            send(msg);
        }

        // 冷卻時間,避免癱瘓系統
        await child_page.waitForTimeout(30 * 1000);
    }
}

我們用一個 changed 來確認空位數是否有變化。
有變化的話,再傳訊息。

完成!


每日鐵人賽熱門 Top 10 (1004)

以 10/04 20:00 ~ 10/05 20:00 文章觀看數增加值排名

  1. +230 JS 07 - 原型方法:欲達則必速
    • 作者: Felix
    • 系列:JavaScript 從 50% 開始,打造函式庫不是問題!
  2. +155 Day 18:數據蒐集、資料視覺化、數據分析
    • 作者: Broccoli Huang
    • 系列:30 天從麻瓜變 Android 工程師
  3. +134 Day20 Android - Retrofit(Get)
    • 作者: chu_jin02
    • 系列:Android 新手入門學習
  4. +133 [Day30] 完結灑花❀ 看完賽心得順便用Python畫 3D 漸層花朵!
    • 作者: lulu_meat
    • 系列:奇怪的知識增加了!原來程式還可以這樣用?!
  5. +133 【Day 20】Google Apps Script - API 篇回顧整理
    • 作者: Jason Hung
    • 系列:「Google Apps Script」 學習筆記
  6. +132 Day 1 無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
    • 作者: 用圖片高效學程式
    • 系列:無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
  7. +122 [面試][資料庫]如何解決高併發情境的商品秒殺問題
    • 作者: 寶寶出頭天
    • 系列:全端工程師生存筆記
  8. +120 [Day2] 抓取每日收盤價
    • 作者: JohnsonTheRock
    • 系列:從零開始使用python打造簡易投資工具
  9. +117 Day 23【Tokens' Owner】FUN SIDE PROJECT
    • 作者: ALu
    • 系列:All In One NFT Website Development
  10. +112 從零開始的8-bit迷宮探險【Level 27】神助攻-老弟幫我配個音效
    • 作者: 雪花冰
    • 系列:從零開始的8-bit迷宮探險!Swift SpriteKit 遊戲開發實戰

上一篇
#20 Telegram Bot Webhook 訊息收發
下一篇
#22 IPAPAPI - IP as Picture API
系列文
JavaScript Easy Go!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言